export function myAtoi (str: string): number {

    const automaton = new Automaton();

    for (let i = 0; i < str.length; i++) {
        automaton.walk(str[i]);
    }
    return automaton.ans * automaton.sign;
}

enum AutoMatonStatus {
    START = 1,
    SIGNED = 2,
    IN_NUMBER = 3,
    END = 4
}

class Automaton {
    /** 正负号 */
    public sign = 1;
    /** 结果 */
    public ans = 0;
    /** 状态映射 */
    private statusMap: Map<AutoMatonStatus, AutoMatonStatus[]>;
    /** 当前状态 */
    private status: AutoMatonStatus;

    constructor () {
        this.statusMap = new Map();
        this.initMap();
        this.status = AutoMatonStatus.START;
    }

    public walk (char: string) {
        this.status = this.statusMap.get(this.status)![this.getCol(char)];
        if (this.status === AutoMatonStatus.IN_NUMBER) {
            this.ans = this.ans * 10 + (<any>char - <any>'0');
            // 注意不要超出边界
            // TODO:
        } else if (this.status === AutoMatonStatus.SIGNED) {
            this.sign = char === '+' ? 1 : -1;
        } 
    }

    private getCol (char: string) {
        if (char === ' ') return 0;         // 空格
        if (char === '+' || char === '-') return 1;
        if (char >= '1' && char <= '9') return 2;
        return 3;
    }

    private initMap () {
        this.statusMap.set(AutoMatonStatus.START, [
            AutoMatonStatus.START,
            AutoMatonStatus.SIGNED,
            AutoMatonStatus.IN_NUMBER,
            AutoMatonStatus.END
        ]);
        this.statusMap.set(AutoMatonStatus.SIGNED, [
            AutoMatonStatus.END,
            AutoMatonStatus.END,
            AutoMatonStatus.IN_NUMBER,
            AutoMatonStatus.END
        ]);
        this.statusMap.set(AutoMatonStatus.IN_NUMBER, [
            AutoMatonStatus.END,
            AutoMatonStatus.END,
            AutoMatonStatus.IN_NUMBER,
            AutoMatonStatus.END
        ]);
        this.statusMap.set(AutoMatonStatus.END, [
            AutoMatonStatus.END,
            AutoMatonStatus.END,
            AutoMatonStatus.END,
            AutoMatonStatus.END
        ]);
    }
}
